package com.agg.persist.xml.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ReflectUtil;
import com.agg.core.base.VoidEnum;
import com.agg.core.base.dto.ColumnDTO;
import com.agg.core.base.dto.ExtDTO;
import com.agg.core.base.dto.PaginationDTO;
import com.agg.core.base.dto.TimeSectionDTO;
import com.agg.core.exception.EntityMapperException;
import com.agg.core.utils.Asserts;
import com.agg.core.utils.Dates;
import com.agg.core.utils.Strings;
import com.agg.persist.xml.mapping.EntityMapper;
import com.agg.persist.xml.mapping.Join;
import com.agg.persist.xml.mapping.Property;
import com.agg.persist.xml.mapping.QueryEnum;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;


public class DruidSQLBuilder {
    protected final Log log = LogFactory.getLog(getClass());
    /**
     *
     * @param em
     * @param t
     * @param ext
     * @param columns
     * @param <T>
     * @return
     */
    public <T> String sql(EntityMapper em, T t, ExtDTO ext, List<ColumnDTO> columns){
        return buildSql(em,t,ext,columns);
    }
    public <T> String sql(EntityMapper em, PaginationDTO<T, VoidEnum, ExtDTO> pagination, List<ColumnDTO> columns){
        return buildSql(em,pagination,columns);
    }
    /**
     *
     * @param em
     * @param t
     * @param columns
     * @param <T>
     * @return
     */
    public <T> String sql(EntityMapper em, T t, List<ColumnDTO> columns){
        return buildSql(em,t,columns);
    }

    /**
     *
     * @param em
     * @param columns
     * @param <T>
     * @return
     */
    public <T> String sql(EntityMapper em,List<ColumnDTO> columns){
        return buildSql(em,columns);
    }

    /**
     * 构建sql
     * @param em
     * @param t
     * @param ext
     * @param columns
     * @param <T>
     * @return
     */
    public <T>String buildSql(EntityMapper em,T t, ExtDTO ext,List<ColumnDTO> columns){
        SQLSelect sqlSelect = new SQLSelect();
        //根据列过滤排除的字段
        List<Property> list= filterColumns(em,columns);
        //关联查询
        List<Join> joins=getJoins(em,columns);
        //构建基本的sql语句
        SQLSelectQueryBlock queryBlock=createQueryBlock(em,columns,list,joins);
        SQLExpr where= queryBlock.getWhere();
        //拼装where
        where=addWhere(where,em,joins,t,ext,list);
        queryBlock.setWhere(where);
        sqlSelect.setQuery(queryBlock);
        String sql = SQLUtils.toSQLString(sqlSelect);
        sql=sql+" "+addOrderBy(em,ext.getAscs(), ext.getDescs());
        System.out.println(" builder sql======="+sql);
        return sql;

    }

    public <T>String buildSql(EntityMapper em,PaginationDTO<T, VoidEnum, ExtDTO> pagination,List<ColumnDTO> columns){
        T t=pagination.getCondition();
        ExtDTO ext=pagination.getOther();
        SQLSelect sqlSelect = new SQLSelect();
        //根据列过滤排除的字段
        List<Property> list= filterColumns(em,columns);
        //关联查询
        List<Join> joins=getJoins(em,columns);
        //构建基本的sql语句
        SQLSelectQueryBlock queryBlock=createQueryBlock(em,columns,list,joins);
        SQLExpr where= queryBlock.getWhere();
        //拼装where
        where=addWhere(where,em,joins,t,ext,list);
        queryBlock.setWhere(where);
        sqlSelect.setQuery(queryBlock);
        String sql = SQLUtils.toSQLString(sqlSelect);
        sql=sql+" "+addOrderBy(em,pagination.getAscs(), pagination.getDescs());
        System.out.println(" build sql======="+sql);
        return sql;

    }
    /**
     * 构建sql
     * @param em
     * @param columns
     * @param <T>
     * @return
     */
    public <T>String buildSql(EntityMapper em,T t,List<ColumnDTO> columns){
        SQLSelect sqlSelect = new SQLSelect();
        //根据列过滤排除的字段
        List<Property> list= filterColumns(em,columns);
        //关联查询
        List<Join> joins=getJoins(em,columns);
        //构建基本的sql语句
        SQLSelectQueryBlock queryBlock=createQueryBlock(em,columns,list,joins);
        SQLExpr where= queryBlock.getWhere();
        //拼装where
        where=addWhere(where,em,joins,t,list);
        queryBlock.setWhere(where);
        sqlSelect.setQuery(queryBlock);
        String sql = SQLUtils.toSQLString(sqlSelect);
        System.out.println(" build sql======="+sql);
        return sql;

    }
    /**
     * 构建sql
     * @param em
     * @param columns
     * @param <T>
     * @return
     */
    public <T>String buildSql(EntityMapper em,List<ColumnDTO> columns){
        SQLSelect sqlSelect = new SQLSelect();
        //根据列过滤排除的字段
        List<Property> list= filterColumns(em,columns);
        //关联查询
        List<Join> joins=getJoins(em,columns);
        //构建基本的sql语句
        SQLSelectQueryBlock queryBlock=createQueryBlock(em,columns,list,joins);
        sqlSelect.setQuery(queryBlock);
        String sql = SQLUtils.toSQLString(sqlSelect);
        System.out.println(" build sql======="+sql);
        return sql;

    }
    private SQLSelectQueryBlock createQueryBlock(EntityMapper em,
                                                 List<ColumnDTO> columns,
                                                 List<Property> list,List<Join> joins){

        SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock();
        //拼装查询字段
        addSelectItem(queryBlock,em,list);
        //为空，则单表查询
        if(joins.isEmpty()){
            //查询单表
            fromTable(queryBlock,em);
        }else{
            //表关联
            fromTables(queryBlock,em,joins);
        }
        return  queryBlock;
    }

    /**
     * 拼装where
     * @param where
     * @param em
     * @param t
     * @param list
     * @param <T>
     * @return
     */
    private <T>SQLExpr addWhere(SQLExpr where,
                                EntityMapper em,
                                List<Join> joins,
                                T t,
                                List<Property> list){
        //所有的条件
        List<SQLExprImpl> exprs=new ArrayList<>();
        //获取逻辑删除的条件
        //   List<SQLExprImpl> logicalDelExprs =getLogicalDelExprs(em,joins);
        //  exprs.addAll(logicalDelExprs);
        //构建实体查询条件
        List<SQLBinaryOpExpr> entityExprs=entityCondition(em ,t,list);
        exprs.addAll(entityExprs);
        //left 为初始化左侧的where条件
        SQLExpr left=where;
        Integer index=0;
        //left 为空默认初始化left
        if(left==null&&!exprs.isEmpty()){
            left=exprs.get(0);
            index++;
        }
        if(exprs.size()>index){
            //拼装到sql
            for(int i=index;i<exprs.size();i++){
                SQLExprImpl opExpr=exprs.get(i);
                SQLBinaryOpExpr append=new SQLBinaryOpExpr();
                append.setLeft(left);
                append.setOperator(SQLBinaryOperator.BooleanAnd);
                append.setRight(opExpr);
                left=append;
            }
        }
        return left;
    }

    /**
     * 拼装where
     * @param where
     * @param em
     * @param t
     * @param ext
     * @param list
     * @param <T>
     * @return
     */
    private <T>SQLExpr addWhere(SQLExpr where,
                                EntityMapper em,
                                List<Join> joins,
                                T t,
                                ExtDTO ext,
                                List<Property> list){
        //所有的条件
        List<SQLExprImpl> exprs=new ArrayList<>();
        //获取逻辑删除的条件
     //   List<SQLExprImpl> logicalDelExprs =getLogicalDelExprs(em,joins);
      //  exprs.addAll(logicalDelExprs);
        //构建实体查询条件
        List<SQLBinaryOpExpr> entityExprs=entityCondition(em ,t,list);
        exprs.addAll(entityExprs);
        //扩展查询
        List<SQLExprImpl> extExprs=extCondition(em,ext,list);
        exprs.addAll(extExprs);
        //left 为初始化左侧的where条件
        SQLExpr left=where;
        Integer index=0;
        //left 为空默认初始化left
        if(left==null&&!exprs.isEmpty()){
            left=exprs.get(0);
            index++;
        }
        if(exprs.size()>index){
            //拼装到sql
            for(int i=index;i<exprs.size();i++){
                SQLExprImpl opExpr=exprs.get(i);
                SQLBinaryOpExpr append=new SQLBinaryOpExpr();
                append.setLeft(left);
                append.setOperator(SQLBinaryOperator.BooleanAnd);
                append.setRight(opExpr);
                left=append;
            }
        }
        return left;
    }

    /**
     * 排序
     * @param ascs
     * @param descs
     * @param em
     * @param <T>
     * @return
     */
    private <T> String addOrderBy(
            EntityMapper em,
            List<String> ascs,List<String> descs ){
        if(Asserts.isNull(ascs)&&Asserts.isNull(descs)){
            return  "";
        }
        //所有字段
        List<Property> list=allColumns(em);
        Map<String,Property> map=list.stream().collect(Collectors.toMap(Property::getName,e->e));
        StringJoiner joiner=new StringJoiner(",");
        if(!Asserts.isNull(ascs)){
            for(String field:ascs){
                if(!map.containsKey(field)){
                    continue;
                }
                Property property=map.get(field);
                joiner.add(property.getOwner()+"."+property.getColumn()+" asc");
            }
        }
        //倒序字段
        if(!Asserts.isNull(descs)){
            for(String field:descs){
                if(!map.containsKey(field)){
                    continue;
                }
                Property property=map.get(field);
                joiner.add(property.getOwner()+"."+property.getColumn()+" desc");
            }
        }

        String orderByStr="order by "+joiner.toString();
        return orderByStr;
    }

    /**
     *  查询选项
     * @param queryBlock
     * @param em
     * @param list
     */
    private void addSelectItem(SQLSelectQueryBlock queryBlock,EntityMapper em,List<Property> list){
        for(Property property:list){
            SQLPropertyExpr colExpr= ExprUtil.getProperExpr(property.getColumn(),property.getOwner());
            if(Asserts.isNotNullOrEmpty(property.getAlias())){
                queryBlock.addSelectItem(colExpr,property.getAlias());
            }else{
                queryBlock.addSelectItem(colExpr);
            }
        }

    }

    /**
     * 单表
     * @param queryBlock
     * @param em
     */
    private void fromTable(SQLSelectQueryBlock queryBlock,EntityMapper em){
        SQLExpr expr=new SQLIdentifierExpr(em.getTable());
        SQLExprTableSource tableSource=new SQLExprTableSource(expr,em.getAlias());
        queryBlock.setFrom(tableSource);
        SQLBinaryOpExpr opExpr=ExprUtil.getEqValExpr("enabled",em.getAlias(),1);
        queryBlock.addCondition(opExpr);
    }

    /**
     * 多表
     * @param queryBlock
     * @param em
     * @param joins
     */
    private void fromTables(SQLSelectQueryBlock queryBlock,EntityMapper em,List<Join> joins){
        //init  join
        SQLJoinTableSource jts=initLeftJoint(em,joins.get(0));
        if(joins.size()>1){
            for(int i=1;i<joins.size();i++){
                Join next=joins.get(i);
                //关联表
                jts=joinNextTable(jts,next);
                //next enabled=1
                SQLBinaryOpExpr opExpr=ExprUtil.getEqValExpr("enabled",next.getLeftOwner(),1);
                jts.addCondition(opExpr);
                //二级关联  t1 inner join t2 on t1.id=t2.id inner join t3 on t2.id=t3.id
                List<Join>  joins2=next.getEntityMapper().getJoins();
                /*if(!Asserts.isNull(joins2)){
                    for(int j=1;j<joins2.size();j++){
                        Join join2=joins2.get(i);
                        //关联表
                        jts=joinNextTable(jts,join2);
                        //next enabled=1
                        SQLBinaryOpExpr opExpr2=ExprUtil.getEqValExpr("enabled",join2.getLeftOwner(),1);
                        jts.addCondition(opExpr2);
                    }
                }*/
               //  二级关联  t1 inner join t2 on t1.id=t2.id inner join t3 on t2.id=t3.id
              // jts=twoJoin(jts,next);
            }
        }
        queryBlock.setFrom(jts);
    }

    /**
     * 二级关联  t1 inner join t2 on t1.id=t2.id inner join t3 on t2.id=t3.id
     * @param jts
     * @param join
     * @return
     */
    private SQLJoinTableSource twoJoin(SQLJoinTableSource jts,Join join){
        List<Join>  joins2=join.getEntityMapper().getJoins();
        if(!Asserts.isNull(joins2)){
            for(int j=0;j<joins2.size();j++){
                Join join2=joins2.get(j);
                //关联表
                jts=joinNextTable(jts,join2);
                //next enabled=1
                SQLBinaryOpExpr opExpr2=ExprUtil.getEqValExpr("enabled",join2.getLeftOwner(),1);
                jts.addCondition(opExpr2);
            }
        }
        return jts;
    }

    /**
     * 初始化左侧表关联
     * @param em
     * @param join
     * @return
     */
    private SQLJoinTableSource initLeftJoint(EntityMapper em,Join join){
        SQLJoinTableSource jts=new SQLJoinTableSource();
        jts.setLeft(em.getTable(),em.getAlias());
        EntityMapper rem=join.getEntityMapper();
        jts.setRight(rem.getTable(),rem.getAlias());
        SQLJoinTableSource.JoinType joinType= SQLJoinTableSource.JoinType.valueOf(join.getJoinType());
        if(joinType==null){
            throw new EntityMapperException("join type not  found");
        }
        jts.setJoinType(joinType);
        //联合查询条件
        joinConditon(jts,join);
        //关联查询 t2 的关联
       // jts=twoJoin(jts,join);
        return jts;

    }

    /**
     * 联合查询的条件
     * @param jts
     */
    private void joinConditon( SQLJoinTableSource jts,Join join ){
        String leftVar=Strings.toLowerCase(join.getLeftKey(),"_");
        String rightVar= Strings.toLowerCase(join.getRightKey(),"_");
        String leftOwner=join.getLeftOwner();
        String rightOwner=join.getRightOwner();
        //join conditon
        SQLBinaryOpExpr opExpr=ExprUtil.getOnEqExpr(leftVar,leftOwner,rightVar,rightOwner);
        //add join conditon
        jts.addCondition(opExpr);
        //逻辑删除
        SQLBinaryOpExpr leftLogicDel=ExprUtil.getEqValExpr("enabled",join.getLeftOwner(),1);
        jts.addCondition(leftLogicDel);
        //逻辑删除
        SQLBinaryOpExpr rightLogicDel=ExprUtil.getEqValExpr("enabled",join.getRightOwner(),1);
        jts.addCondition(rightLogicDel);
    }

    /**
     * 下个节点 联合查询
     * @param left
     * @param join
     * @return
     */
    private SQLJoinTableSource joinNextTable(SQLJoinTableSource left,Join join){
        SQLJoinTableSource jts=new SQLJoinTableSource();
        jts.setLeft(left);
        EntityMapper jem=join.getEntityMapper();
        jts.setRight(jem.getTable(),jem.getAlias());
        //join type: left join,inner join...
        SQLJoinTableSource.JoinType joinType= SQLJoinTableSource.JoinType.valueOf(join.getJoinType());
        if(joinType==null){
            throw new EntityMapperException("join type not  found");
        }
        jts.setJoinType(joinType);
        String leftVar= Strings.toLowerCase(join.getLeftKey(),"_");
        String rightVar=Strings.toLowerCase(join.getRightKey(),"_");
        String leftOwner=join.getLeftOwner();
        String rightOwner=join.getRightOwner();
        //join conditon
        SQLBinaryOpExpr opExpr=ExprUtil.getOnEqExpr(leftVar,leftOwner,rightVar,rightOwner);
        //add join conditon
        jts.addCondition(opExpr);
        return jts;
    }

    /**
     * 所有字段
     * @param em
     * @return
     */
    private List<Property> allColumns(EntityMapper em){
        List<Property> allList= new ArrayList<>();
        allList.addAll(em.getProperties());
        //所有的连接
        List<Join> joins=getJoins(em,null);
        //获取连接相关的属性
        for (Join join:joins){
            EntityMapper jem= join.getEntityMapper();
            if(jem==null){
                continue;
            }
            List<Property> properties= jem.getProperties();
            if(properties!=null&&!properties.isEmpty()){
                allList.addAll(join.getEntityMapper().getProperties());
            }
        }
        return allList;
    }

    /**
     * 所有字段
     * @param em
     * @param columns
     * @return
     */
    private List<Property> allColumns(EntityMapper em,List<ColumnDTO> columns){
        List<Property> allList=  new ArrayList<>();
        allList.addAll(em.getProperties());
        //所有的连接
        List<Join> joins=getJoins(em,columns);
        //获取连接相关的属性
        for (Join join:joins){
            EntityMapper jem= join.getEntityMapper();
            if(jem==null){
                continue;
            }
            List<Property> properties= jem.getProperties();
            if(properties!=null&&!properties.isEmpty()){
                allList.addAll(join.getEntityMapper().getProperties());
            }
        }
        return allList;
    }

    /**
     * 过滤列
     * @param em
     * @param columns
     * @return
     */
    private List<Property> filterColumns(EntityMapper em,List<ColumnDTO> columns){
        //获取所有字段
        List<Property> allList=allColumns(em);
        //前端传递 列过滤为空，则默认显示全部
        if(columns==null){
            return allList;
        }
        List<Property> filterList=new ArrayList<>();
        //first table columns
        List<ColumnDTO> tableColumns=getCurrTableColumns(em,columns);
        List<Property> propertys=filterPropertys(em,allList,tableColumns);
        filterList.addAll(propertys);
        List<Join> joins= getJoins(em,columns);
        //join  table columns
        for(Join join:joins){
           EntityMapper jem=join.getEntityMapper();
           if(jem==null){
               continue;
           }
           List<ColumnDTO> jTableColumns=getCurrTableColumns(jem,columns);
           List<Property> jPropertys=filterPropertys(jem,allList,jTableColumns);
           filterList.addAll(jPropertys);
        }
        return filterList;
    }

    /**
     * 根据em,columns获取属性
     * @param em
     * @param allList
     * @param columns
     * @return
     */
    private List<Property> filterPropertys(EntityMapper em,List<Property> allList,List<ColumnDTO> columns){
        List<Property> filterList=new ArrayList<>();
        List<Property> list=allList.stream()
                .filter(e->e.getOwner().equals(em.getAlias()))
                .collect(Collectors.toList());
        for(Property property:list){
            String name=property.getName();
            for(ColumnDTO dto: columns){
                if(dto.getName().equals(name)){
                    filterList.add(property);
                }
            }
        }
        return filterList;
    }

    /**
     * 当前表的字段，根据columns，table 获取列
     * @param em
     * @param columns  包含所有表的列，此参数为接收前端的展示列
     * @return
     */
    private List<ColumnDTO> getCurrTableColumns(EntityMapper em,List<ColumnDTO> columns){
        if(columns==null){
            return new ArrayList<>();
        }
        String table=em.getTable();
        List<ColumnDTO> currTableColumns= columns.stream()
                .filter(e->e.getTable().equals(table))
                .collect(Collectors.toList());
        return  currTableColumns;

    }
    /**
     * 关联查询
     * @param em
     * @param columns
     * @return
     */
    private List<Join> getJoins(EntityMapper em,List<ColumnDTO> columns){
        List<Join> joinEms= new ArrayList<>();
        List<Join> joins=em.getJoins();
        //为空，则返回：表示单表查询
        if(joins==null||joins.isEmpty()){
            return joinEms;
        }
        //第一层关联查询
        for (Join join: joins){
            //关联查询的实体映射模型
            EntityMapper twoEm=join.getEntityMapper();
            //映射模型为空，则跳至下个join
            if(twoEm==null){
                log.info("twoEm is null:"+join.getMapperId());
                continue;
            }
            //判断：该表是有查询字段
            boolean je= isJoin(join,columns);
            //第二层关联查询
            List<Join> twoJoins=getJoins(twoEm,columns);
            //子表有查询字段则获取
            boolean isTwoNotEmpty=!twoJoins.isEmpty();
            if(je||isTwoNotEmpty){
                joinEms.add(join);
            }
            if(isTwoNotEmpty){
                joinEms.addAll(twoJoins);
            }
        }
        return joinEms;
    }
    private boolean isJoin(Join join,List<ColumnDTO> columns){
        List<Property> properties= join.getEntityMapper().getProperties();
        //为空，默认所有的字段都为显示
        if(columns==null||columns.isEmpty()){
            return true;
        }
        for(Property p:properties){
            for(ColumnDTO columnDTO:columns){
                String name=columnDTO.getName();
                if(name.equals(p.getName())){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 逻辑删除 条件
     * @param em
     * @return
     */
    private List<SQLExprImpl> getLogicalDelExprs(EntityMapper em, List<Join> joins){
        List<SQLExprImpl> list=new ArrayList<>();
        SQLBinaryOpExpr opExpr=ExprUtil.getEqValExpr("enabled",em.getAlias(),1);
        list.add(opExpr);
        for(Join join:joins){
            SQLBinaryOpExpr joinExpr=ExprUtil.getEqValExpr("enabled",join.getEntityMapper().getAlias(),1);
            list.add(joinExpr);
        }
        return list;

    }
    /**
     * 实体查询条件
     * @param em
     * @param t
     * @param properties
     * @param <T>
     * @return
     */
    private <T> List<SQLBinaryOpExpr> entityCondition(EntityMapper em,T t, List<Property> properties)  {
        String className= em.getClazz();
        List<SQLBinaryOpExpr> list= new ArrayList<>();
        try{
            Class clz=Class.forName(className);
            Map<String,Field> fieldMap= ReflectUtil.getFieldMap(clz);
            String holder="cm";
            for(Property p:properties){
                if(!fieldMap.containsKey(p.getName())){
                    continue;
                }
                if(!ReflectUtil.hasField(t.getClass(),p.getName())){
                    continue;
                }
                Object val=ReflectUtil.getFieldValue(t,p.getName());
                if(Asserts.isNullOrEmpty(val)){
                    continue;
                }
                Field field= fieldMap.get(p.getName());
                if(String.class==field.getType()){
                    if(Asserts.equalsVal(p.getQuery(),QueryEnum.eq.name())){
                        //如果查询条件约束为，需要使用等号时
                        SQLBinaryOpExpr opExpr=ExprUtil.getEqExpr(p,holder,p.getOwner());
                        list.add(opExpr);
                    }else if(Asserts.equalsVal(p.getQuery(), QueryEnum.nq.name())){
                        //不可查询的将不能封装为条件查询
                        continue;
                    }else{
                        //字符串，默认使用like
                        SQLBinaryOpExpr opExpr=ExprUtil.getLikeExpr(p,p.getName(),holder);
                        list.add(opExpr);
                    }
                }else {
                    //非字符串，使用等号比较
                    SQLBinaryOpExpr opExpr=ExprUtil.getEqExpr(p,holder,p.getOwner());
                    list.add(opExpr);
                }
            }
        }catch (  ClassNotFoundException e){
            throw  new EntityMapperException("class:"+className+" not found");
        }
        return list;

    }

    /**
     * 其他查询条件
     * @param em
     * @param extDTO
     * @param properties
     * @param <T>
     * @return
     */
    private <T> List<SQLExprImpl> extCondition(EntityMapper em,
                                               ExtDTO extDTO,
                                               List<Property> properties)  {
        String keyword=extDTO.getKeyword();
        List<SQLExprImpl> list= new ArrayList<>();
        String holder="ex";
        if(Asserts.isNotNullOrEmpty(keyword)){
             String varName="keyword";
             //like:为 or...or...or... 结构
             SQLBinaryOpExpr like=null;
             for (Property property:properties){
                 if(Asserts.equalsVal(property.getQuery(),QueryEnum.like.name())){
                     like=(like==null)?
                             ExprUtil.getLikeExpr(property,varName,holder)
                             :addNextLike(like,property,varName,holder);
                 }
             }
             if(like!=null){
                 list.add(like);
             }
        }
        //时间区间查询
        List<SQLExprImpl> timeSectionExprs= getTimeSectionExprs(extDTO,properties,holder);
        list.addAll(timeSectionExprs);
        //主表 id 的in（....）集合查询
        if( extDTO.getIds()!=null&& !extDTO.getIds().isEmpty()){
            SQLInListExpr inListExpr= ExprUtil.inIdsExpr(em.getAlias(), extDTO.getIds());
            list.add(inListExpr);
        }
        //column in(...): 某个字段in查询
        if(extDTO.getIn()!=null&&!extDTO.getIn().isEmpty()){
            for(Map.Entry<String,List<Object>> entry:extDTO.getIn().entrySet()){
                Optional<Property> optional=properties.stream()
                        .filter(p->p.getName().equals(entry.getKey())).findFirst();
                if(!optional.isPresent()){
                    continue;
                }
                //根据对比的属性获取
                Property property=optional.get();
                //某字段的in(...) 查询
                SQLInListExpr inListExpr= ExprUtil.inExpr(property.getOwner(),property.getColumn(), entry.getValue());
                list.add(inListExpr);
            }

        }
        return list;
    }

    /**
     * 时间区间的条件
     * @param extDTO
     * @param properties
     * @return
     */
    private List<SQLExprImpl> getTimeSectionExprs( ExtDTO extDTO,
                                                   List<Property> properties,
                                                   String holder){
        //时间区间查询
        List<TimeSectionDTO> sections=extDTO.getTimeSections();
        List<SQLExprImpl> list=new ArrayList<>();
        if(sections==null||sections.isEmpty()){
            return list;
        }
        Map<String,TimeSectionDTO> sectionMap=sections.stream()
                .collect(Collectors.toMap(TimeSectionDTO::getName,t->t));
        String startTime=null;
        String endTime=null;
        String format="yyyy-MM-dd HH:mm:ss";
        for(Property property:properties){
            if(QueryEnum.time.name().equals(property.getQuery())
                    &&sectionMap.containsKey(property.getName())){
                TimeSectionDTO sectionDTO=sectionMap.get(property.getName());
                //开始时间
                if(sectionDTO.getStartTime()!=null){
                    startTime= Dates.format(sectionDTO.getStartTime(),format);
                    SQLBinaryOpExpr geExpr=ExprUtil.getGeCharExpr(property,startTime,holder);
                    list.add(geExpr);
                }
                //结束时间
                if(sectionDTO.getEndTime()!=null){

                    endTime= Dates.format(sectionDTO.getEndTime(),format);
                    SQLBinaryOpExpr leExpr=ExprUtil.getLeCharExpr(property,endTime,holder);
                    list.add(leExpr);
                }

            }
        }

        return list;
    }


    /**
     * 增加下个条件 ，条件关联使用or
     * @param left
     * @param property
     * @return
     */
    private SQLBinaryOpExpr addNextLike(SQLBinaryOpExpr left,Property property,String varName,String holder){
        SQLBinaryOpExpr expr=new SQLBinaryOpExpr();
        SQLBinaryOpExpr next=ExprUtil.getLikeExpr(property,varName,holder);
        expr.setLeft(left);
        expr.setRight(next);
        expr.setOperator(SQLBinaryOperator.BooleanOr);
        return expr;
    }
}
